<template>
  <div
    class="w-screen bg-hex-f6f6f6"
    :style="{height: `calc(100vh - ${navigationHeight}px)`}"
    @touchstart="handleScreenTouchStart"
    @touchend="handleScreenTouchEnd"
    @touchcancel="handleScreenTouchEnd">
    <NavigationBar title-text="我的地址" background-color="#f6f6f6" />
    <Message ref="message" />
    <Loading ref="loading" fullscreen mask-color="#f6f6f6" start-from-init />

    <div class="address-book-container w-screen bg-hex-f6f6f6">
      <div class="address-records w-screen pt-8rpx">
        <div
          class="address w-screen flex px-50rpx py-20rpx mb-20rpx bg-white"
          :class="addressTouchingId === `address${index}` ? 'address--touching' : ''"
          v-for="(address, index) in addressRecords"
          :key="index"
          :data-name="`address${index}`"
          @click="handleClick"
          @touchstart="handleTouchStart"
          @touchend="handleTouchEnd"
          @touchcancel="handleTouchEnd"
          @longpress="handleLongPress">
          <div class="info h-full">
            <div class="contact-name text-30rpx text-black">
              {{ formatContactName(address.contactName) }}
              <text class="contact-phone ml-20rpx text-26rpx text-hex-888">
                {{ address.contactPhone }}
              </text>
            </div>
            <div class="contact-address mt-14rpx text-24rpx text-hex-555">
              {{ formatAddressDetail(address.addressDetail, address.areaName) }}
            </div>
            <div
              class="default-address h-36rpx px-14rpx mt-14rpx mb-6rpx text-22rpx text-white bg-primary"
              v-show="address.isDefaultAddress">
              默认地址
            </div>
          </div>
          <div
            class="btn w-70rpx flex items-center text-36rpx text-primary"
            v-if="!isSelectMode"
            :data-name="`address${index}`"
            @click.stop="handleEdit">
            <i class="fas fa-pen" />
          </div>
        </div>

        <div class="load-more-container">
          <div v-show="existMore && !loadingMore" class="load-more">
            <text>{{ releaseToLoadMore ? '松开加载更多' : '下拉加载更多' }}</text>
          </div>
          <div
            v-show="loadingMore"
            class="load-more loading-more">
            <Loading ref="loadingMoreRef" mask-color="#f6f6f6" />
          </div>
          <div
            v-show="!existMore && addressRecords.length !== 0"
            class="load-more">
            <text>没有更多了哦 ~</text>
          </div>
        </div>
        <div
          class="empty wh-full flex-column justify-center text-center"
          :style="{minHeight: `calc(100vh - ${navigationHeight + 40}px)`}"
          v-if="!addressRecords.length">
          <div class="row w-full flex justify-center py-8rpx text-26rpx text-hex-888">
            一个地址都没有噢
          </div>
          <div class="row w-full flex justify-center py-8rpx text-26rpx text-hex-888">
            <div
              class="btn ml-20rpx my-10rpx px-24rpx py-10rpx text-28rpx bg-primary text-white"
              @click="handleAddAddress">
              新增地址
            </div>
          </div>
        </div>
      </div>

      <div
        class="new-address-btn w-screen fixed bottom-0 left-0 bg-white transition-opacity duration-300"
        v-if="!isSelectMode && addressRecords.length"
        :style="{opacity: `${isShowBottomBtn && !loadingMore ? 1 : 0}`}"
        @click="handleAddAddress">
        <div class="btn-text mx-auto my-18rpx text-center text-30rpx text-white bg-primary">
          新增地址
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import Message from '@/components/message/src/message.vue'
  import {MessageMethod} from '@/components/message'
  import Loading from '@/components/loading/src/loading.vue'
  import {LoadingMethod} from '@/components/loading'
  import NavigationBar from '@/components/navigation-bar/src/navigation-bar.vue'
  import {useSystemStore} from '@/store'
  import {addressApi} from '@/service/api'
  import {UserAddressDto} from '@/service/api/modules/address/response'
  import {gotoPage} from '@/common/utils'
  import {formatContactName, formatAddressDetail, getContactGender} from '@/common/filters'

  const {windowWidth, navigationHeight, primaryColor} = storeToRefs(useSystemStore())

  const eventChannel = ref<any>(null) //页面事件通信
  const message = ref<InstanceType<typeof Message> & MessageMethod>(null)
  const loading = ref<InstanceType<typeof Loading> & LoadingMethod>(null)
  const loadingMoreRef = ref<InstanceType<typeof Loading> & LoadingMethod>(null)

  type Address = {
    id?: number
    contactName?: string
    contactPhone?: string
    contactGender?: number
    areaCode?: string
    areaName?: Array<string | undefined>
    addressDetail?: string
    isDefaultAddress?: boolean
  }

  const addressRecords = ref<Array<UserAddressDto>>([]) //我的地址数组
  const addressTouchingId = ref<string>('') //当前触摸地址记录的数据名
  const pageSize = 15 //分页大小
  const currentPage = ref<number>(1) //当前页码
  const loadingMore = ref<boolean>(false) //是否处于加载更多状态
  const existMore = ref<boolean>(true) //是否存在更多地址记录
  const scrolling = ref<boolean>(false) //页面是否正在滑动
  const isShowBottomBtn = ref<boolean>(true) //是否显示底部按钮区域
  const waitTimer = ref<number>(NaN) //等待加载的计时器
  const waitingLoadMore = ref<boolean>(false) //是否等待加载更多地址记录
  const releaseToLoadMore = ref<boolean>(false) //是否显示“松开加载更多”提示
  const screenTouching = ref<boolean>(false) //是否正在触摸屏幕
  const isSelectMode = ref<boolean>(false) //是否为选择地址模式
  const scrollTop = ref<number>(0) //页面滚动高度

  /**
   * 获取我的地址数据
   * @param pageNumber 分页查询页码，不传参数默认为查询第一页
   */
  const getMyAddress = useDebounceFn((pageNumber: number = 1): void => {
    addressApi.getMyAddressList({
      pageSize: pageSize,
      pageNumber: pageNumber
    }).then(res => {
      let addressTemp: Array<Address> = []
      res.data?.records?.forEach(addressRecords => {
        addressTemp.push({
          id: addressRecords.id,
          contactName: addressRecords.contacts,
          contactPhone: addressRecords.phone,
          areaCode: addressRecords.areaCode,
          areaName: [addressRecords.province, addressRecords.city, addressRecords.area],
          addressDetail: addressRecords.addressDetail,
          isDefaultAddress: addressRecords.isDefault
        })
      })
      if (pageNumber === 1) {
        addressRecords.value = addressTemp
      } else {
        addressTemp.map(address => addressRecords.value.push(address))
      }
      if (typeof res.data?.pages === 'number' && res.data?.pages <= currentPage.value) {
        if (pageNumber !== 1) {
          existMore.value = false
        }
        currentPage.value = res.data.pages
        if (typeof res.data?.total === 'number' && res.data?.total <= pageSize) {
          existMore.value = false
        }
      } else {
        existMore.value = true
      }
    }).catch(err => {
      console.error(err)
      message.value.error({
        text: '获取地址失败',
        direction: 'top'
      })
    }).finally(() => {
      loadingMore.value = false
      loading.value.stopLoading()
    })
  }, 300)
  getMyAddress()

  // 地址点击事件
  const handleClick = (e: Event): void => {
    if (isSelectMode.value) {
      let addressIndex = Number((e.currentTarget as HTMLElement).dataset.name?.replace('address', ''))
      let address = JSON.parse(JSON.stringify(addressRecords.value[addressIndex])) //强制深拷贝
      try {
        eventChannel.value.emit('acceptDataFromOpenedPage', {
          address: address
        })
        uni.navigateBack()
      } catch (e) {
        message.value.error({
          text: '网络异常',
          direction: 'top'
        })
      }
    } else {
      handleEdit(e)
    }
  }

  // 监听地址触摸开始事件
  const handleTouchStart = (e: Event): void => {
    addressTouchingId.value = (e.currentTarget as HTMLElement).dataset.name ?? ''
  }

  // 监听地址触摸结束事件
  const handleTouchEnd = (): void => {
    addressTouchingId.value = ''
  }

  // 监听地址长按事件
  const handleLongPress = (e: Event): void => {
    uni.vibrateShort({})
    const addressIndex: number = Number((e.currentTarget as HTMLElement).dataset.name?.replace('address', '') ?? '')
    const address: Address = JSON.parse(JSON.stringify(addressRecords.value[addressIndex])) //强制深拷贝
    uni.showActionSheet({
      itemList: isSelectMode.value ? ['复制'] : ['复制', '设为默认地址', '删除地址'],
      success: res => {
        if (res.tapIndex === 0) {
          //复制地址
          uni.setClipboardData({
            data: `${formatContactName(address.contactName ?? '')} ${address.contactPhone} ${formatAddressDetail(address.addressDetail ?? '', address.areaName)}`
          })
        } else if (res.tapIndex === 1) {
          //设为默认地址
          loading.value.startLoading()
          addressApi.setDefaultAddress({
            addressId: address.id
          }).then(() => {
            getMyAddress()
            setTimeout(() => {
              message.value.success({
                text: '设置成功',
                direction: 'top'
              })
            }, 500)
          }).catch(err => {
            loading.value.stopLoading()
            setTimeout(() => {
              message.value.error({
                text: '设置失败',
                direction: 'top'
              })
            }, 500)
            console.error(err)
          })
        } else if (res.tapIndex === 2) {
          //删除地址
          uni.showModal({
            title: '',
            content: '删除地址后将无法恢复，确定删除？',
            confirmColor: primaryColor.value,
            success: res => {
              if (res.confirm) {
                //确定删除地址
                addressApi.deleteOneAddress({
                  addressId: address.id
                }).then(() => {
                  getMyAddress()
                  setTimeout(() => {
                    message.value.success({
                      text: '删除成功',
                      direction: 'top'
                    })
                  }, 500)
                }).catch(err => {
                  //删除地址失败
                  loading.value.stopLoading()
                  setTimeout(() => {
                    message.value.error({
                      text: '删除失败',
                      direction: 'top'
                    })
                  }, 500)
                  console.error(err)
                })
              }
            }
          })
        }
      }
    })
  }

  // 地址编辑按钮点击事件
  const handleEdit = (e: Event): void => {
    if (!!(e.currentTarget as HTMLElement).dataset.name) {
      const addressIndex = Number((e.currentTarget as HTMLElement).dataset.name?.replace('address', '') ?? '')
      const address: Address = JSON.parse(JSON.stringify(addressRecords.value[addressIndex])) //强制深拷贝
      const contactNameTemp = getContactGender(address.contactName ?? '')
      address.contactName = contactNameTemp.name
      address.contactGender = contactNameTemp.gender
      uni.navigateTo({
        url: '/pagesByUser/address-book/subpages/edit-address/edit-address',
        success: res => {
          res.eventChannel.emit('editAddress', {data: address})
        }
      })
    }
  }

  // 新增地址按钮点击事件
  const handleAddAddress = (): void => {
    gotoPage('/pagesByUser/address-book/subpages/edit-address/edit-address')
  }

  // 监听屏幕触摸开始事件
  const handleScreenTouchStart = (): void => {
    screenTouching.value = true
  }

  // 监听屏幕触摸结束事件
  const handleScreenTouchEnd = (): void => {
    screenTouching.value = false
    releaseToLoadMore.value = false
    if (scrolling.value && !releaseToLoadMore.value) {
      isShowBottomBtn.value = true
    }
  }

  // 监听加载更多的状态变化
  watch(
    () => loadingMore.value,
    (nval, oval) => {
      if (nval && !oval && addressRecords.value.length !== 0) {
        loadingMoreRef.value.startLoading({
          width: windowWidth.value,
          height: 54
        })
      }
      if (!nval && oval) {
        loadingMoreRef.value.stopLoading()
      }
    }
  )

  // 监听等待加载更多的状态
  watch(
    () => waitingLoadMore.value,
    (nval, oval) => {
      if (nval && !oval) {
        waitTimer.value = setInterval(() => {
          if (isShowBottomBtn) {
            loadingMore.value = true
            currentPage.value += 1
            getMyAddress(currentPage.value)
            waitingLoadMore.value = false
            clearInterval(waitTimer.value)
          }
          setTimeout(() => {
            waitingLoadMore.value = false
            clearInterval(waitTimer.value)
          }, 2000)
        }, 300)
      }
    }
  )

  onPageScroll((e) => {
    isShowBottomBtn.value && (isShowBottomBtn.value = false)
    scrollTop.value = e.scrollTop
    scrolling.value = true
    let timer = setTimeout(() => {
      if (scrollTop.value === e.scrollTop && !screenTouching) {
        scrollTop.value = e.scrollTop
        scrolling.value = false
        !releaseToLoadMore && (isShowBottomBtn.value = true)
        clearTimeout(timer)
      }
    }, 300)
  })

  onReachBottom(() => {
    releaseToLoadMore.value = true
    existMore.value && (waitingLoadMore.value = true)
  })

  onLoad(() => {
    //@ts-ignore
    eventChannel.value = getCurrentInstance().proxy.getOpenerEventChannel()
    try {
      eventChannel.value.on('selectAddress', (data: any) => {
        isSelectMode.value = !!data.data
      })
    } catch (e) {
      isSelectMode.value = false
    }
  })

  onShow(() => {
    const instance = getCurrentInstance()
    nextTick(() => {
      //@ts-ignore
      const loginSuccess: boolean = instance?.proxy?.$passedParams?.loginSuccess ?? false
      // loading.value.startLoading()
      getMyAddress()
    })
  })
</script>

<style scoped lang="scss">
  @import 'address-book';
</style>
